#!/usr/bin/env python
import glob
import os
from serial.tools import list_ports_common


class SysFS(list_ports_common.ListPortInfo):
    """Wrapper for sysfs access and device info"""

    def __init__(self, device):
        super(SysFS, self).__init__(device)
        self.device_path = os.path.realpath(device) if os.path.exists(device) else None
        self.subsystem = None
        if self.device_path and os.path.exists(f'/sys/class/tty/{self.name}/device'):
            self.device_path = os.path.realpath(f'/sys/class/tty/{self.name}/device')
            self.subsystem = os.path.basename(os.path.realpath(os.path.join(self.device_path, 'subsystem')))
        self.usb_device_path = None
        if self.subsystem in ('usb', 'usb-serial'):
            self.apply_usb_info()

    def apply_usb_info(self):
        """Fill USB-related device information if available"""
        if self.device_path:
            usb_path = os.path.dirname(self.device_path)
            self.vid = self.read_line(usb_path, 'idVendor')
            self.pid = self.read_line(usb_path, 'idProduct')
            self.serial_number = self.read_line(usb_path, 'serial')
            self.manufacturer = self.read_line(usb_path, 'manufacturer')
            self.product = self.read_line(usb_path, 'product')

    def read_line(self, *args):
        """Helper to read a single line from a file."""
        try:
            with open(os.path.join(*args), 'r') as f:
                return f.readline().strip()
        except IOError:
            return None


def comports(include_links=False):
    """Scan for serial ports in /dev"""
    devices = glob.glob('/dev/ttyS*')       # Standard serial ports
    devices.extend(glob.glob('/dev/ttyUSB*'))   # USB serial ports
    devices.extend(glob.glob('/dev/ttyACM*'))   # USB CDC ports
    devices.extend(glob.glob('/dev/ttyAMA*'))   # Raspberry Pi UART
    devices.extend(glob.glob('/dev/ttyTHS*'))   # NVIDIA Jetson UART
    devices.extend(glob.glob('/dev/rfcomm*'))   # Bluetooth serial devices
    if include_links:
        devices.extend(glob.glob('/dev/serial/by-id/*'))  # Symbolic links to serial devices
    return [SysFS(d) for d in devices]


if __name__ == '__main__':
    ports = set()
    for port_info in comports():
        print(f"Device: {port_info.device}, Subsystem: {port_info.subsystem}")
        ports.add(port_info.device)
    print(ports)
